﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMail.Modules.Messages.Models;
using AMail.Common;
using AMail.Common.Interfaces.Data;
using System.Collections.ObjectModel;
using Microsoft.Practices.Composite.Events;
using AMail.Common.Events;
using System.Windows.Input;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Diagnostics;
using AMail.Modules.Messages.Views;
using Elentok.Common.Wpf;
using System.Windows;
using AMail.Common.Interfaces.Services;
using Elentok.Common.Wpf.ViewModels.Dialogs;
using System.Windows.Media.Imaging;
using Elentok.Common.Wpf.Services;

namespace AMail.Modules.Messages.ViewModels
{
  public class MessageListViewModel : ViewModelBase, IMessageListViewModel
  {
    #region Private Fields
    
    private IEventAggregator eventAggregator;
    private IDataService dataService;

    private ReadOnlyCollection<IMailMessage> selectedMessages;
    private IMailFolder folder;
    private ObservableCollection<IMailMessage> messages;
    private string sortBy;
    
    #endregion

    public const string DefaultSortBy = "Date ASC";

    #region Ctor

    public MessageListViewModel(IEventAggregator eventAggregator, IDataService dataService)
    {
      this.eventAggregator = eventAggregator;
      this.dataService = dataService;
      eventAggregator.GetEvent<SelectedFolderChangedEvent>().Subscribe(OnSelectedFolderChanged);

      this.Folder = null;
      this.SortBy = DefaultSortBy;

      this.SelectedMessagesChangedCommand 
        = new DelegateCommand<ReadOnlyCollection<IMailMessage>>(ExecuteSelectedMessagesChangedCommand);
      this.ViewSourceCommand 
        = new DelegateCommand<object>(ExecuteViewSourceCommand, CanExecuteViewSourceCommand);
      this.ImportFromClipboardCommand
        = new DelegateCommand<object>(ExecuteImportFromClipboardCommand);
      this.ImportFromGmailCommand
        = new DelegateCommand<object>(ExecuteImportFromGmailCommand);

      this.DeleteMessagesCommand
        = new DelegateCommand<object>(
            ExecuteDeleteMessagesCommand,
            CanExecuteDeleteMessagesCommand);
            

    }
    
    #endregion

    #region Event Handlers

    private void OnSelectedFolderChanged(IMailFolder folder)
    {
      this.Folder = folder;
    }
    
    #endregion

    #region Selected-Messages-Changed Command
    private void ExecuteSelectedMessagesChangedCommand(ReadOnlyCollection<IMailMessage> selectedMessages)
    {
      this.selectedMessages = selectedMessages;
      this.eventAggregator.GetEvent<SelectedMessagesChangedEvent>().Publish(selectedMessages);
    }
    #endregion

    #region Import-From-Clipboard Command
    private void ExecuteImportFromClipboardCommand(object parameter)
    {
      if (!Clipboard.ContainsText())
        return;

      string text = Clipboard.GetText();
      byte[] bytes = Encoding.UTF8.GetBytes(text);

      var message = this.dataService.CreateMessage(bytes);
      if (this.Folder != null)
      {
        this.Folder.Messages.Add(message);
      }
    }
    #endregion

    #region ViewSource Command

    private bool CanExecuteViewSourceCommand(object parameter)
    {
      return this.selectedMessages != null &&
        this.selectedMessages.Count == 1;
    }

    private void ExecuteViewSourceCommand(object parameter)
    {
      IMailMessage message = this.selectedMessages[0];

      MessageSourceViewModel sourceViewModel = new MessageSourceViewModel(message);
      MessageSourceView view = new MessageSourceView(sourceViewModel);
      view.Show();
    }

    #endregion

    #region Import-From-Gmail Command
    private void ExecuteImportFromGmailCommand(object param)
    {
      WizardDialogViewModel viewModel = new WizardDialogViewModel();
      viewModel.AddPage(
        new ImageWizardPageViewModel
        {
          Title = "Import from Gmail - Step 1",
          Message = "1. Open a message in Gmail.\r\n2. Press the arrow button on the top-right of the message.", 
          Image = new BitmapImage(new Uri("/AMail.Modules.Messages;component/Images/GmailStep1.png", UriKind.Relative))
        });

      var image2 = new BitmapImage(new Uri("/AMail.Modules.Messages;component/Images/GmailStep2.png", UriKind.Relative));

      viewModel.AddPage(
        new ImageWizardPageViewModel
        {
          Title = "Import from Gmail - Step 2",
          Message = "Select the \"Show Original\" menu item",
          Image = image2
        });

      viewModel.AddPage(
        new ImageWizardPageViewModel
        {
          Title = "Import from Gmail - Step 3",
          Message = "1. Copy the source of the mail (from the new window that was opened).\r\n" + 
            "2. In AMail, use the \"Import from Clipboard\" menu item",
        });

      viewModel.Show(false);
    }
    #endregion

    #region IMessageListViewModel Members

    /// <summary>
    /// Gets or sets the displayed folder
    /// </summary>
    public IMailFolder Folder
    {
      get
      {
        return this.folder;
      }
      set
      {
        if (this.folder == value)
          return;

        this.folder = value;
        OnPropertyChanged("Folder");

        if (value == null)
          this.Messages = new ObservableCollection<IMailMessage>();
        else
          this.Messages = value.Messages;
      }
    }

    /// <summary>
    /// Gets or sets the messages
    /// </summary>
    public ObservableCollection<IMailMessage> Messages
    {
      get
      {
        return this.messages;
      }
      private set
      {
        if (this.messages == value)
          return;

        this.messages = value;
        OnPropertyChanged("Messages");
      }
    }

    /// <summary>
    /// Gets or sets the sortBy
    /// </summary>
    public string SortBy
    {
      get
      {
        return this.sortBy;
      }
      set
      {
        if (this.sortBy == value)
          return;

        this.sortBy = value;
        OnPropertyChanged("SortBy");
      }
    }

    public ICommand SelectedMessagesChangedCommand { get; private set; }
    public ICommand ViewSourceCommand { get; private set; }
    public ICommand ImportFromClipboardCommand { get; private set; }
    public ICommand ImportFromGmailCommand { get; private set; }

    /// <summary>
    /// Gets the delete messages command.
    /// </summary>
    /// <value>The delete messages command.</value>
    public ICommand DeleteMessagesCommand { get; private set; }

    #endregion

    #region Delete Messages Command


    private void ExecuteDeleteMessagesCommand(object param)
    {
      if (this.selectedMessages.Count == 0)
        return;

      string confirmationMessage = null;

      if (this.selectedMessages.Count == 1)
        confirmationMessage = string.Format("Delete '{0}'?", this.selectedMessages[0].Subject);
      else
        confirmationMessage = string.Format("Delete {0} messages?", this.selectedMessages.Count);
      
      var result = MessageBox.Show(
            confirmationMessage, 
            "AMail - Confirm", 
            MessageBoxButton.YesNo, 
            MessageBoxImage.Question);

      if (result == MessageBoxResult.Yes)
      {
        foreach (var message in this.selectedMessages)
          message.ParentFolder = null;
      }
    }

    private bool CanExecuteDeleteMessagesCommand(object param)
    {
      return this.selectedMessages.Count > 0;
    }

    #endregion
  }
}
